import { $baseUrl } from 'services/api/client';
import type { PayloadAction } from '@reduxjs/toolkit';
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { randomNum } from 'common/util/randomInt';
import { Artist } from 'features/parameters/components/Parameters/ModalParameters/Artist/ArtistItem';
import { ArtisticEffect } from 'features/parameters/components/Parameters/ModalParameters/ArtisticEffect/ArtisticEffectItem';
import { ArtisticStyle } from 'features/parameters/components/Parameters/ModalParameters/ArtisticStyle/ArtisticStyleItem';
import { PaintingStyle } from 'features/parameters/components/Parameters/ModalParameters/PaintingStyle/PaintingStyleItem';
import { PatternDesign } from 'features/parameters/components/Parameters/ModalParameters/PatternDesign/PatternDesignItem';
import { logger } from 'app/logging/logger';
import { getToken } from 'common/util/token';
type PaintingMenuContentType =
  | Artist
  | ArtisticEffect
  | ArtisticStyle
  | PaintingStyle
  | PatternDesign;

type PresetItem =
  | 'parameters.artist'
  | 'parameters.artisticEffect'
  | 'parameters.artisticStyle'
  | 'parameters.paintingStyle'
  | 'parameters.patternDesign';
export type UserPaintingMenuItem = {
  i18nKey: PresetItem;
  paintingMenuContentList: PaintingMenuContentType[];
  id: string;
};

export interface SelectedPresetStyleState {
  artist: Array<Artist>;
  paintingStyle: Array<PaintingStyle>;
  artisticStyle: Array<ArtisticStyle>;
  artisticEffect: Array<ArtisticEffect>;
  patternDesign: Array<PatternDesign>;
  selectedPatternDesign: Array<string>;
  selectedArtist: Array<string>;
  selectedPaintingStyle: Array<string>;
  selectedArtisticStyle: Array<string>;
  selectedArtisticEffect: Array<string>;
  randomStyle: Partial<{
    artist: Artist;
    artisticStyle: ArtisticStyle;
    artisticEffect: ArtisticEffect;
    paintingStyle: PaintingStyle;
  }>[];
  byRandomStyle: boolean;
  userPaintingMenuConfig: string[];
  presetMap: any;
}

const initialPresetState: SelectedPresetStyleState = {
  artist: [],
  artisticStyle: [],
  artisticEffect: [],
  paintingStyle: [],
  patternDesign: [],
  selectedPatternDesign: [],
  selectedArtist: [],
  selectedPaintingStyle: [],
  selectedArtisticStyle: [],
  selectedArtisticEffect: [],
  randomStyle: [],
  byRandomStyle: false,
  userPaintingMenuConfig: [],
  presetMap: {},
};

export const presetSlice = createSlice({
  name: 'preset',
  initialState: initialPresetState,
  reducers: {
    setArtist: (state, action: PayloadAction<Artist[]>) => {
      const artist = action.payload;
      const typeList = ['风景示例', '肖像示例', '建筑示例'];
      const formattedArtist = artist.map((a) => {
        // 艺术家原作，风格图片， 绘画示例图片
        let images = [];
        if (a.imgUrl) {
          images = a.imgUrl.split(',').map((i: string, index: number) => ({
            imageSrc: i,
            imageDesc: typeList[index],
          }));
        }

        return {
          ...a,
          images,
          avatarSrc: a.avatarSrc || '',
        };
      });
      state.artist = formattedArtist;
    },

    setArtisticStyle: (state, action: PayloadAction<ArtisticStyle[]>) => {
      state.artisticStyle = action.payload;
    },
    setArtisticEffect: (state, action: PayloadAction<ArtisticEffect[]>) => {
      state.artisticEffect = action.payload;
    },
    setPaintingStyle: (state, action: PayloadAction<PaintingStyle[]>) => {
      state.paintingStyle = action.payload;
    },
    setPatternDesign: (state, action: PayloadAction<PatternDesign[]>) => {
      state.patternDesign = action.payload;
    },

    setSelectedPatternDesign: (state, action: PayloadAction<string[]>) => {
      state.selectedPatternDesign = action.payload;
    },

    setSelectedArtist: (state, action: PayloadAction<string[]>) => {
      state.selectedArtist = action.payload;
    },

    setSelectedPaintingStyle: (state, action: PayloadAction<string[]>) => {
      state.selectedPaintingStyle = action.payload;
    },
    setSelectedArtisticStyle: (state, action: PayloadAction<string[]>) => {
      state.selectedArtisticStyle = action.payload;
    },
    setSelectedArtisticEffect: (state, action: PayloadAction<string[]>) => {
      state.selectedArtisticEffect = action.payload;
    },

    resetSelectedPresetStyleState: (state) => {
      return {
        ...state,
        ...initialPresetState,
      };
    },

    setByRandomStyle: (state, action: PayloadAction<boolean>) => {
      state.byRandomStyle = action.payload;
    },

    setRandomStyle: (state, action: PayloadAction<number>) => {
      const { artist, paintingStyle, artisticEffect, artisticStyle } = state;

      const iterations = action.payload;
      const randomStyleArr = [];
      for (let i = 0; i < iterations; i++) {
        const artistNum = randomNum(artist.length - 1);
        const paintingStyleNum = randomNum(paintingStyle.length - 1);
        const artisticStyleNum = randomNum(artisticStyle.length - 1);
        const artisticEffectNum = randomNum(artisticEffect.length - 1);

        randomStyleArr.push({
          artist: artist[artistNum],
          paintingStyle: paintingStyle[paintingStyleNum],
          artisticEffect: artisticEffect[artisticEffectNum],
          artisticStyle: artisticStyle[artisticStyleNum],
        });
      }

      state.randomStyle = randomStyleArr;
      state.byRandomStyle = true;
    },
    setUserPaintingMenuConfig: (state, action: PayloadAction<string[]>) => {
      state.userPaintingMenuConfig = action.payload;
    },
    setPresetMap: (state, action: PayloadAction<any>) => {
      state.presetMap = action.payload;
    },
  },
});

export const {
  setArtist,
  setArtisticStyle,
  setArtisticEffect,
  setPaintingStyle,
  setPatternDesign,
  setSelectedPatternDesign,
  setSelectedArtisticEffect,
  setSelectedArtisticStyle,
  setSelectedPaintingStyle,
  setSelectedArtist,
  resetSelectedPresetStyleState,
  setRandomStyle,
  setByRandomStyle,
  setUserPaintingMenuConfig,
  setPresetMap,
} = presetSlice.actions;

export default presetSlice.reducer;

export const getUserPaintingMenuConfig = createAsyncThunk(
  'user/getUserPaintingMenuConfig',
  async (_params, { dispatch, rejectWithValue }) => {
    const log = logger('system');
    try {
      const headersOption: HeadersInit = {
        'Content-Type': 'application/json',
      };
      if (getToken()) {
        headersOption['Authorization'] = `Bearer ${getToken()}`;
      }
      const headers = new Headers(headersOption);
      const response = await fetch(
        `${$baseUrl.get() ?? ''}/web/web/paintingMenu`,
        {
          method: 'GET',
          headers: headers,
        }
      );
      const { rt } = await response.json();
      const paintingPreset: UserPaintingMenuItem[] = rt;

      // log.info({ paintingPreset }, 'Received Painting Preset');

      const configKeys = paintingPreset.map(({ i18nKey }) => i18nKey);
      dispatch(setUserPaintingMenuConfig(configKeys));

      const presetMap = {
        patternDesign: {},
        artist: {},
        paintingStyle: {},
        artisticStyle: {},
        artisticEffect: {},
      };
      const buildMap = (paintingMenuContentList: PaintingMenuContentType[]) => {
        return paintingMenuContentList.reduce((p, t) => {
          p[t.id] = t;
          return p;
        }, {} as Record<(typeof paintingMenuContentList)[number]['id'], PaintingMenuContentType>);
      };

      paintingPreset.forEach(({ i18nKey, paintingMenuContentList }) => {
        switch (i18nKey) {
          case 'parameters.artist':
            dispatch(setArtist(paintingMenuContentList as Artist[]));
            presetMap.artist = buildMap(paintingMenuContentList as Artist[]);
            break;
          case 'parameters.paintingStyle':
            dispatch(
              setPaintingStyle(paintingMenuContentList as PaintingStyle[])
            );
            presetMap.paintingStyle = buildMap(
              paintingMenuContentList as PaintingStyle[]
            );
            break;
          case 'parameters.artisticStyle':
            dispatch(
              setArtisticStyle(paintingMenuContentList as ArtisticStyle[])
            );
            presetMap.artisticStyle = buildMap(
              paintingMenuContentList as ArtisticStyle[]
            );
            break;
          case 'parameters.artisticEffect':
            dispatch(
              setArtisticEffect(paintingMenuContentList as ArtisticEffect[])
            );
            presetMap.artisticEffect = buildMap(
              paintingMenuContentList as ArtisticEffect[]
            );
            break;
          case 'parameters.patternDesign':
            dispatch(
              setPatternDesign(paintingMenuContentList as PatternDesign[])
            );
            presetMap.patternDesign = buildMap(
              paintingMenuContentList as PatternDesign[]
            );
            break;
        }
      });
      dispatch(setPresetMap(presetMap));
      return paintingPreset;
    } catch (error) {
      return rejectWithValue({ error });
    }
  }
);
